define(function(require, exports, module) {

  // var Backbone = require('backbone');
  var $ = require('jquery');
  var _ = require('underscore');
  // var jsonview = require('jsonview');
  var tmpl = require('text!../tmpl.html');
  var d3 = require('d3v3')
  var animation = require('hy5b/animation/index')

  const width = 400, height = 300;
  const durPerPx = 4;
  const flowLen = 120;

  function main() {
    var $app = $('<div id="app">');
    $('#main').html($app);

    $app.append(tmpl);

    var rotate = 0;
    var step = 10;
    var w = 300, h = 150;
    const baseRadian = Math.atan(w / h);
    const R = Math.sqrt(w * w + h * h) / 2;
    var x = 0, y = 0, radian = 0;
    var x0 = w / 2, y0 = h / 2;
    $('#delete').click(function() {
      rotate-=step;
      radian = rotate * Math.PI / 180;
      x = x0 + R * Math.sin(radian - baseRadian);
      y = y0 - R * Math.cos(radian - baseRadian);
      d3.select("#myGradientRotate").attr('gradientTransform', `translate(${x} ${y}) rotate(${rotate})`)
    })
    $('#add').click(function() {
      rotate+=step;
      radian = rotate * Math.PI / 180;
      x = x0 + R * Math.sin(radian - baseRadian);
      y = y0 - R * Math.cos(radian - baseRadian);
      d3.select("#myGradientRotate").attr('gradientTransform', `translate(${x} ${y}) rotate(${rotate})`)
    })

    const svg = d3.select('.svg').append('svg')
      .classed('visible', true)
      .attr('width', width)
      .attr('height', height)

    
    const flowLenHalf = flowLen / 2

    const _svgEl = svg

    const defs = _svgEl.append('defs')

    defs.append('filter')
      .attr('id', 'filter3791')
      .append('feGaussianBlur')
      .attr('stdDeviation', 5)

    defs.append('filter')
      .attr('id', 'filter3792')
      .append('feGaussianBlur')
      .attr('in', 'StrokePaint')
      .attr('stdDeviation', 2)

    setStarLightLineGradientColor(
      defs.append('linearGradient')
        .attr('id', 'filter1')
        .attr('gradientTransform', 'rotate(90)')
    )
    setStarLightLineGradientColor(
      defs.append('linearGradient')
        .attr('id', 'filter2')
    )

    const leftStar = _svgEl.append('g').attr('transform', `translate(0 ${flowLenHalf})`)
    const topStar = _svgEl.append('g').attr('transform', `translate(${flowLenHalf})`)
    leftStar.append('path')
      .attr('d', 'm7.1 40 30 10 6 40 8-40 27-10-27-12-6-20-11 20z')
      .attr('fill', '#fdfdff')
      .attr('filter', 'url(#filter3791)')
      .attr('transform', 'scale(0.3) translate(-43 -38)')

    if (0) {
      //多段线模拟 tapered 光线
      for (var i = 0; i < 4; i++) {
        leftStar.append('line')
          .attr('x1', 0)
          .attr('y1', -flowLenHalf * (4 - i) / 4)
          .attr('x2', 0)
          .attr('y2', flowLenHalf * (4 - i) / 4)
          .attr('stroke', '#fdfdff')
          .attr('opacity', 0.25 * (i + 1))
      }
    } else if (0) {
      //渐变填充模拟 tapered 光线
      leftStar.append('rect')
        .attr('width', 1)
        .attr('height', flowLen)
        .attr('y', -flowLenHalf)
        .attr('fill', 'none')
        .attr('stroke', 'url(#filter1)')
    }
    
    topStar.append('path')
      .attr('d', 'm7.1 40 30 10 6 40 8-40 27-10-27-12-6-20-11 20z')
      .attr('fill', '#fdfdff')
      .attr('filter', 'url(#filter3791)')
      .attr('transform', 'scale(0.3) translate(-43 -38)')
    if (0) {
      topStar.append('rect')
        .attr('width', flowLen)
        .attr('height', 1)
        .attr('x', -flowLenHalf)
        .attr('fill', 'none')
        .attr('stroke', 'url(#filter2)')
      
    }
    const lightCycleG = _svgEl.append('g')

    if (0) {
      //点光模拟 tapered 光线
      lightCycleG.append('path')
        .attr('id', 'path2')
        .attr('d', `M 0,0 L ${width},0 L ${width},${height} L 0,${height} Z`)
        .attr('fill', 'none')
      const duan = 100
      let opacity = 0
      for (var i = 0; i < duan; i++) {
        opacity = i > duan / 2 ? (duan - i) * 2 / duan : i * 2 / duan;
        lightCycleG.append('circle')
          .attr('fill', '#ffffff')
          .attr('opacity', opacity)
          .attr('cx', 0)
          .attr('cy', 0)
          .attr('r', 1)
          .append('animateMotion')
          .attr('dur', (durPerPx * (width + height)) + 'ms')
          .attr('begin', durPerPx * i + 'ms')
          .attr('repeatCount', 'indefinite')
          .append('mpath')
          .attr('xlink:href', '#path2')
      }
      return
    }

    const lightCycleStroke = lightCycleG.append('linearGradient')
      .attr('id', 'myGradientRotate1')
      .attr('gradientUnits', 'userSpaceOnUse')
    setStarLightLineGradientColor(lightCycleStroke, true)

    lightCycleG.append('rect')
      .attr('width', width)
      .attr('height', height)
      .attr('stroke-width', 2)
      .attr('fill', 'none')
      .attr('stroke', 'url(#myGradientRotate1)')
      .attr('fill', 'url(#myGradientRotate1)')
    
    topStar.transition()
      .duration(300)
      .ease('linear')
      .attr('transform', `translate(${width - flowLenHalf})`)
      .remove()
    leftStar.transition()
      .duration(300)
      .ease('linear')
      .attr('transform', `translate(0 ${height - flowLenHalf})`)
      .remove()

    if (0) {
      _svgEl.append('rect')
        .attr('fill', 'none')
        .attr('stroke', '#fdfdff')
        .attr('width', width)
        .attr('height', height)
        .attr('stroke-linecap', 'round')
        .attr('stroke-linejoin', 'round')
        .attr('stroke-dasharray', [flowLen, width + height - flowLen])
        .attr('stroke-dashoffset', 2 * height + width + flowLen)
        .append('animate')
        .attr('attributeType', 'XML')
        .attr('attributeName', 'stroke-dashoffset')
        .attr('from', 2 * height + width + flowLen)
        .attr('to', height + flowLen)
        .attr('dur', (durPerPx * (width + height)) + 'ms')
        .attr('repeatCount', 'indefinite')
    } else {
      (function() {
        const w = width, h = height;
        const baseRadian = Math.atan(w / h);
        const R = Math.sqrt(w * w + h * h) / 2;
        var x = 0, y = 0, radian = 0;
        var x0 = w / 2, y0 = h / 2;
        const T = durPerPx * (w + h); //ms
        var rotate = 0;
        const degreePerFrame = 360 / T * animation.FRAME60;
        function step() {
          radian = rotate * Math.PI / 180;
          // x = x0 + R * Math.sin(radian - baseRadian);
          // y = y0 - R * Math.cos(radian - baseRadian);
          d3.select("#myGradientRotate1").attr('gradientTransform', `translate(${x} ${y}) rotate(${rotate})`)
          rotate += degreePerFrame;
          requestAnimationFrame(step)
        }

        step()
      }())
    }
      
  }

  function setStarLightLineGradientColor(linearGradient, rotate) {
    linearGradient.append('stop')
      .attr('offset', '0%')
      .attr('stop-color', 'rgba(253,253,255,0)')
    if (rotate) {
      linearGradient.append('stop')
        .attr('offset', '20%')
        .attr('stop-color', 'rgba(253,253,255,0)')
    }
    linearGradient.append('stop')
      .attr('offset', '50%')
      .attr('stop-color', 'rgba(253,253,255,1)')
    if (rotate) {
      linearGradient.append('stop')
        .attr('offset', '80%')
        .attr('stop-color', 'rgba(253,253,255,0)')
    }
    linearGradient.append('stop')
      .attr('offset', '100%')
      .attr('stop-color', 'rgba(253,253,255,0)')

  }

  return main;
})
